package org.rency.common.redis.service.impl;

import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.rency.common.redis.service.RedisService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

public class DefaultRedisTemplateServiceImpl<K, V> extends AbstractRedisTemplate<K, V> implements RedisService<K, V> {

	private static final Logger logger = LoggerFactory.getLogger(DefaultRedisTemplateServiceImpl.class);
	
	@Override
	public V get(K key) {
		logger.debug("get redis cache data for [{}].",key);
		return this.getRedisTemplate().opsForValue().get(key);
	}

	@Override
	public boolean set(K key, V value) {
		logger.debug("set redis cache data for [{}], data [{}].",key,value);
		this.getRedisTemplate().opsForValue().set(key, value);
		return true;
	}

	@Override
	public boolean set(K key, V value, long expireTime) {
		logger.debug("set redis cache data for [{}], data [{}], expire time [{}]m.",key,value,expireTime);
		this.getRedisTemplate().opsForValue().set(key, value, expireTime, TimeUnit.SECONDS);
		return true;
	}

	@Override
	public V remove(K key) {
		logger.debug("remove redis cache data for [{}].",key);
		boolean hasKey = this.hasKey(key);
		if(!hasKey){
			return null;
		}
		V value = this.getRedisTemplate().opsForValue().get(key);
		this.getRedisTemplate().opsForValue().getOperations().delete(key);
		return value;
	}
	
	@Override
	public void remove(List<K> keys) {
		this.getRedisTemplate().delete(keys);
	}

	@Override
	public boolean sendMessage(String channel, Serializable message) {
		logger.info("redis send message, to [{}], message : [{}].",channel,message);
		this.getRedisTemplate().convertAndSend(channel, message);
		return true;
	}

	@SuppressWarnings("unchecked")
	@Override
	public Set<K> keyList() {
		logger.debug("get redis cache key list.");
		return this.getRedisTemplate().keys((K)"*");
	}

	@Override
	public boolean expirtAt(K key, long expireTime) {
		logger.debug("set redis cache data for [{}] expire time at [{}]m after.",key,expireTime);
		if(!this.hasKey(key)){
			return false;
		}
		return this.expirtAt(key, expireTime, TimeUnit.SECONDS);
	}

	@Override
	public boolean expirtAt(K key, long expireTime, TimeUnit timeUnit) {
		logger.debug("set redis cache data for [{}] expire time at [{}]{} after.",key,expireTime,timeUnit.name());
		if(!this.hasKey(key)){
			return false;
		}
		return this.getRedisTemplate().expire(key, expireTime, timeUnit);
	}

	@Override
	public boolean expirtAt(K key, Date date) {
		logger.debug("set redis cache data for [{}] expire at {}.",key,date);
		if(!this.hasKey(key)){
			return false;
		}
		return this.getRedisTemplate().expireAt(key, date);
	}

	@Override
	public long getExpire(K key) {
		logger.debug("get redis cache expire time for key [{}].",key);
		if(!this.hasKey(key)){
			return 0;
		}
		return this.getRedisTemplate().getExpire(key);
	}
	
	@Override
	public boolean hasKey(K key) {
		return this.getRedisTemplate().opsForValue().getOperations().hasKey(key);
	}
		
}